﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Windows.Forms;
using JiraGenCommon;
using JiraGenCommon.Helpers;
using JiraGenCommon.JiraServices;
using JiraGenCommon.Model;
using JiraGenerator.Properties;
using JiraGenCommon.Constants;

namespace JiraGenerator
{
    public partial class JiraGenerator : JiraBaseForm
    {
        List<JiraGenContract> _listJiraGen = null;
        private string _bugIssuetype = string.Empty;
        private string _subtaskIssuetype = string.Empty;
        private string _taskIssuetype = string.Empty;
        private string _userStoryIssuetype = string.Empty;
        private const bool _defaultValueTreeCheckBox = false;

        public JiraGenerator()
        {
            InitializeComponent();

            tvApplication.AfterCheck += new TreeViewEventHandler(tvApplication_AfterCheck);
        }

        void tvApplication_AfterCheck(object sender, TreeViewEventArgs e)
        {
            // The code only executes if the user caused the checked state to change.
            if (e.Action != TreeViewAction.Unknown)
            {
                if (e.Node.Nodes.Count > 0)
                {
                    /* Calls the CheckAllChildNodes method, passing in the current 
                    Checked value of the TreeNode whose checked state changed. */
                    this.CheckAllChildNodes(e.Node, e.Node.Checked);
                }
            }
        }

        // Updates all child tree nodes recursively.
        private void CheckAllChildNodes(TreeNode treeNode, bool nodeChecked)
        {
            foreach (TreeNode node in treeNode.Nodes)
            {
                node.Checked = nodeChecked;
                if (node.Nodes.Count > 0)
                {
                    // If the current node has child nodes, call the CheckAllChildsNodes method recursively.
                    this.CheckAllChildNodes(node, nodeChecked);
                }
            }
        }

        private void btnBrowse_Click(object sender, EventArgs e)
        {
            //Stream myStream = null;
            btnNext.Enabled = true;

            if (openPBLFile.ShowDialog() == DialogResult.OK)
            {
                try
                {
                    var excelFile = openPBLFile.FileName;
                    txtFilePath.Text = excelFile;

                    var listSheetName = ExcelHelper.GetExcelSheetNames(excelFile, UIUtils.IsNewExtension(openPBLFile.FileName));// UIUtils.GetListSheetName(dataSet);
                    if (listSheetName == null)
                    {
                        btnNext.Enabled = false;
                        return;
                    }

                    cboSheetName.DataSource = listSheetName;
                    cboSheetName.Refresh();
                }
                catch (Exception ex)
                {
                    txtFilePath.Text = string.Empty;
                    btnNext.Enabled = false;
                    UIUtils.ShowMessageBox(string.Format("{0}{1}",
                        Resources.JiraGenerator_btnBrowse_Click_Cannot_read_file_from_disk__Original_error__, ex.Message),
                                       MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
        }

        private void btnNext_Click(object sender, EventArgs e)
        {
            if (cboSheetName.SelectedIndex == -1)
            {
                UIUtils.ShowMessageBox(Resources.Please_choose_sheet_to_process, MessageBoxButtons.OK,
                                       MessageBoxIcon.Information);
                cboSheetName.Focus();
                return;
            }

            var projectKey = cboProject.SelectedValue.ToString();

            // Bind versions
            UIUtils.BindVersions(cboFixVersion, projectKey);

            tabJiraGenerator.SelectedIndex = 1;
            btnFinish.Text = Resources.JiraGenerator_btnNext_Click_Finish;
        }

        private void tabJiraGenerator_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (tabJiraGenerator.SelectedIndex == 1 && string.IsNullOrEmpty(txtFilePath.Text.Trim()))
            {
                tabJiraGenerator.SelectedIndex = 0;
            }
        }

        private void CreateTreeView()
        {
            tvApplication.Nodes.Clear();

            TreeNode node;
            tvApplication.CheckBoxes = true;

            if (_listJiraGen != null)
                foreach (var jiraGenContract in _listJiraGen)
                {
                    // Add a root node.
                    node = tvApplication.Nodes.Add(Guid.NewGuid().ToString(), jiraGenContract.Sprints);
                    node.Checked = _defaultValueTreeCheckBox;

                    if (jiraGenContract.Tasks != null)
                        foreach (var jiraTask in jiraGenContract.Tasks)
                        {
                            var jiraKeyString = !string.IsNullOrEmpty(jiraTask.JiraKey) ? string.Format(" (Jira Key: {0})", jiraTask.JiraKey) : string.Empty;

                            // Add a node as a child of the previously added node.
                            var childNode = node.Nodes.Add(jiraTask.TaskKey, string.Format("{0}{1}", jiraTask.Summary, jiraKeyString));
                            childNode.Checked = _defaultValueTreeCheckBox;


                            // Add subtask if any
                            if (jiraTask.SubTasks != null)
                            {
                                foreach (var subTask in jiraTask.SubTasks)
                                {
                                    if (chkOTR.Checked)
                                    {
                                        if (subTask.Summary == "Testing")
                                        {
                                            var subTaskKeyString = subTask.JiraKey != null ? string.Format(" (Jira Key: {0})", subTask.JiraKey) : string.Empty;
                                            var subTaskNode = childNode.Nodes.Add(subTask.TaskKey, string.Format("{0}{1}", subTask.Summary, subTaskKeyString));
                                            subTaskNode.Checked = _defaultValueTreeCheckBox;
                                        }
                                    }
                                    else
                                    {
                                        var subTaskKeyString = subTask.JiraKey != null ? string.Format(" (Jira Key: {0})", subTask.JiraKey) : string.Empty;
                                        var subTaskNode = childNode.Nodes.Add(subTask.TaskKey, string.Format("{0}{1}", subTask.Summary, subTaskKeyString));
                                        subTaskNode.Checked = _defaultValueTreeCheckBox;
                                    }
                                }
                            }
                        }
                }
        }

        private void btnFinish_Click(object sender, EventArgs e)
        {
            if (!CheckFixVersion()) return;

            var flagProcessing = false;

            try
            {
                btnFinish.Text = Resources.Processing____;
                btnFinish.Enabled = false;

                // get all checked node in the tree
                int checkedCount;
                var checkedNodes = UIUtils.GetTreeNodeCheckedStatus(tvApplication, out checkedCount);

                pbStatus.Maximum = checkedCount;
                pbStatus.Value = 0;

                var fixVersion = cboFixVersion.SelectedValue.ToString();

                var listUS = new Dictionary<string, string>();

                var otrValue = chkOTR.Checked;

                foreach (var jiraGenContract in _listJiraGen)
                {
                    if (jiraGenContract.Tasks != null)
                    {
                        foreach (var jiraTask in jiraGenContract.Tasks)
                        {
                            // only import to Jira for the new Task, don't apply for existing task
                            if (checkedNodes.ContainsKey(jiraTask.TaskKey) && string.IsNullOrEmpty(jiraTask.JiraKey))
                            {
                                // create user story
                                var usAssignee = string.IsNullOrEmpty(jiraTask.Assignee)
                                                                       ? GlobalVariables.Current.JiraDefaultUser
                                                                       : jiraTask.Assignee;

                                var userStory = JiraService.Instance.CreateIssue(cboProject.SelectedValue.ToString(),
                                                                                 jiraTask.Summary, jiraTask.Description,
                                                                                 usAssignee, _userStoryIssuetype,
                                                                                 fixVersion, otrValue ? jiraTask.DevEstimate : string.Empty);

                                if (userStory != null && jiraTask.SubTasks != null && jiraTask.SubTasks.Count > 0)
                                {
                                    // update US to synch
                                    listUS.Add(jiraTask.RowNumber.ToString(), userStory.key);

                                    // update jira key of JiraTask
                                    jiraTask.JiraKey = userStory.key;

                                    foreach (var task in jiraTask.SubTasks)
                                    {
                                        if (checkedNodes.ContainsKey(task.TaskKey))
                                        {
                                            if (string.Compare(task.Summary, Resources.Development, true) == 0)
                                            {
                                                if (!otrValue)
                                                {
                                                    var assignee = string.IsNullOrEmpty(task.Assignee)
                                                                       ? GlobalVariables.Current.JiraDefaultUser
                                                                       : task.Assignee;
                                                    var subTaskDev = JiraService.Instance.CreateSubTask(task.Project,
                                                                                                    task.Summary,
                                                                                                    task.Description,
                                                                                                    assignee,
                                                                                                    task.DevEstimate,
                                                                                                    userStory.key,
                                                                                                    _subtaskIssuetype,
                                                                                                    fixVersion);
                                                    task.JiraKey = subTaskDev.key;
                                                }
                                            }
                                            else
                                            {
                                                var assignee = string.IsNullOrEmpty(task.Assignee)
                                                                       ? GlobalVariables.Current.JiraDefaultUser
                                                                       : task.Assignee;
                                                var subTaskTest = JiraService.Instance.CreateSubTask(task.Project,
                                                                                                     task.Summary,
                                                                                                     task.Description,
                                                                                                     assignee,
                                                                                                     string.Empty,
                                                                                                     userStory.key,
                                                                                                     _subtaskIssuetype,
                                                                                                     fixVersion);
                                                task.JiraKey = subTaskTest.key;
                                            }


                                            pbStatus.Value += 1;
                                        }
                                    }
                                }

                                pbStatus.Value += 1;
                            }
                        }
                    }
                }

                if (pbStatus.Value < checkedCount)
                {
                    pbStatus.Value = checkedCount;
                }

                flagProcessing = true;

                // sync Jira to file
                ExcelHelper.SyncFromJiraToExcel(openPBLFile.FileName, cboSheetName.SelectedValue.ToString(), listUS);

                UIUtils.ShowMessageBox(Resources.Create_Jira_s_tasks_successful__Take_a_look_on_the_tree_view_above_for_the_Jira_key,
                        MessageBoxButtons.OK, MessageBoxIcon.Information);

                btnFinish.Enabled = false;
                btnFinish.Text = Resources.Done;

                pbStatus.Value = 0;

                CreateTreeView();
            }
            catch (Exception exception)
            {
                UIUtils.ShowMessageBox(string.Format(Resources.Occurs_error_when_creating_Jira_s_task__Error_message__0_, exception.Message),
                                               MessageBoxButtons.OK, MessageBoxIcon.Error);
                
                LogHelper.Write(exception.Message, LogLevel.Error);

                btnFinish.Text = Resources.Finish;
                btnFinish.Enabled = true;

                if (!flagProcessing)
                    tvApplication.Nodes.Clear();
            }
        }

        private bool CheckFixVersion()
        {
            if (cboFixVersion.SelectedIndex == -1)
            {
                UIUtils.ShowMessageBox(Resources.Please_choose_fix_version_for_Jira_tasks, MessageBoxButtons.OKCancel,
                                       MessageBoxIcon.Exclamation);
                cboFixVersion.Focus();
                return false;
            }
            return true;
        }

        private void JiraGenerator_Load(object sender, EventArgs e)
        {
            _bugIssuetype = ConfigurationSettings.AppSettings["issue_type_bug"];
            _taskIssuetype = ConfigurationSettings.AppSettings["issue_type_task"];
            _subtaskIssuetype = ConfigurationSettings.AppSettings["issue_type_subtask"];
            _userStoryIssuetype = ConfigurationSettings.AppSettings["issue_type_user_story"];

            pbStatus.Value = 0;

            // Bind project 
            try
            {
                var remoteProject = JiraService.Instance.GetProjects();
                if (remoteProject != null && remoteProject.Length > 0)
                {
                    cboProject.DataSource = remoteProject;
                    cboProject.DisplayMember = "name";
                    cboProject.ValueMember = "key";
                    cboProject.Refresh();
                }
            }
            catch (Exception)
            {
                UIUtils.ShowMessageBox(
                    Resources.JiraGenerator_JiraGenerator_Load_Can_not_get_projects_from_Jira__please_check_your_Jira_SOAP_Service_URL_is_correct_or_not_on_Preference,
                    MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void cboSheetName_SelectedIndexChanged(object sender, EventArgs e)
        {
            try
            {
                if (cboSheetName.SelectedIndex == 0)
                {
                    ClearTreeView();
                    return;
                }

                btnFinish.Enabled = false;

                var projectKey = cboProject.SelectedValue.ToString();

                var fileName = openPBLFile.FileName;
                _listJiraGen = ExcelHelper.ExcelToJiraParser(fileName, projectKey,
                                UIUtils.IsNewExtension(fileName), UIUtils.ConvertToSheetname(cboSheetName.SelectedValue.ToString()));

                if (_listJiraGen == null)
                {
                    UIUtils.ShowMessageBox(Resources.Can_not_read_data_from_template_file,
                               MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                else
                {
                    if (_listJiraGen.Count == 0)
                    {
                        UIUtils.ShowMessageBox(Resources.Click_Don_t_have_any_data_in_template_file,
                               MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                    }
                    else
                    {
                        // Bind data to TreeView
                        if (_listJiraGen != null)
                        {
                            CreateTreeView();
                        }

                        btnFinish.Enabled = true;
                    }
                }
            }
            catch (Exception exception)
            {
                UIUtils.ShowMessageBox(exception.Message, MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void chkOTR_CheckedChanged(object sender, EventArgs e)
        {
            CreateTreeView();
        }

        private void ClearTreeView()
        {
            tvApplication.Nodes.Clear();
        }
    }
}
